﻿using AutoMapper;
using DFGK.IRepository;
using DFGK.IService;
using DFGK_WMS.Model.Dto;
using DFGK_WMS.Model.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
using static System.Collections.Specialized.BitVector32;

namespace DFGK.Service
{
    public class MenuService : BaseService, IMenuService
    {
        private readonly IMenuRepository _menuRepository;
        private readonly IMenuActionRepository _menuActionRepository;
        private readonly IRoleMenuActionRepository _roleMenuActionRepository;
        private readonly IActionRepository _actionRepository;
        private readonly IUnitOfWork _unitOfWork;
        public MenuService(IMapper mapper, IMenuRepository menuRepository, IMenuActionRepository menuActionRepository, IRoleMenuActionRepository roleMenuActionRepository, IActionRepository actionRepository, IUnitOfWork unitOfWork) : base(mapper)
        {
            _menuRepository = menuRepository;
            _menuActionRepository = menuActionRepository;
            _roleMenuActionRepository = roleMenuActionRepository;
            _actionRepository = actionRepository;
            _unitOfWork = unitOfWork;
        }

        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public bool DelMenuItem(long mid)
        {
            var mobj = _menuRepository.QueryEntityById(mid);
            if (mobj == null) 
            {
                return false;
            }
            _menuRepository.DelEntity(mobj);
            //查询角色菜单操作中该角色拥有的所有权限并删除
            var rmalist = _roleMenuActionRepository.GetEntityWhereAll(x => x.MenuId == mid);
            if (rmalist.Any())
                _roleMenuActionRepository.DelEntityList(rmalist.ToList());
            //查询菜单操作关系表并删除
            var malist = _menuActionRepository.GetEntityWhereAll(x => x.MenuId == mid);
            if (malist.Any())
                _menuActionRepository.DelEntityList(malist.ToList());
            return _unitOfWork.SaveChangesEntity();
        }

        /// <summary>
        /// 加载分配权限列表
        /// </summary>
        /// <param name="rid"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public List<MenuRoleMenuActionDto> GetMenuActionList(long rid)
        {
            //所有菜单
            var mlist = _menuRepository.GetEntityAlls();
            //角色菜单按钮关系
            var rmalist = _roleMenuActionRepository.GetEntityAlls();
            //菜单和按钮的关系
            var malist = _menuActionRepository.GetEntityAlls();
            //所有按钮
            var alist = _actionRepository.GetEntityAlls(); ;

            //递归获取所有菜单
            return GetMenuDtoList(mlist.ToList(), malist.ToList(), alist.ToList(), rmalist.ToList(), 0, rid);
        }

        /// <summary>
        /// 递归获取所有菜单
        /// </summary>
        /// <param name="list">菜单列表</param>
        /// <param name="malist">菜单按钮表</param>
        /// <param name="alist">按钮表</param>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="pid">父级Id</param>
        /// <param name="rid">角色Id</param>
        /// <returns></returns>
        public static List<MenuRoleMenuActionDto> GetMenuDtoList(List<Menu> list, List<MenuAction> malist, List<DFGK_WMS.Model.Models.Action> alist, List<RoleMenuAction> rmalist, long pid, long rid)
        {
            var menuDtoList = new List<MenuRoleMenuActionDto>();

            foreach (var menu in list.Where(x => x.ParentId == pid))
            {
                var menuDto = new MenuRoleMenuActionDto
                {
                    //Id
                    id = menu.Id,
                    //父级Id
                    ParentId = menu.ParentId,
                    //路径
                    MenuUrl = menu.MenuUrl,
                    Meta = new MetaDto
                    {
                        //菜单名称
                        MenuName = menu.MenuName,
                        //菜单图标
                        MenuIcon = menu.MenuIcon,
                    },
                    //状态
                    Status = menu.Status,
                    //排序编号
                    DisplayOrder = menu.DisplayOrder
                };

                var children = GetMenuDtoList(list, malist, alist, rmalist, menu.Id, rid);

                if (children.Count > 0)
                {
                    menuDto.children = children;
                }
                else
                {
                    var actionDtoList = GetActionDtoList(malist, alist, menu.Id, rmalist, rid);

                    if (actionDtoList.Count > 0)
                    {
                        menuDto.Action = actionDtoList;
                    }
                    menuDto.children = new List<MenuRoleMenuActionDto>();
                }

                menuDto.IsChecked = GetRoleMenuDtoList(rmalist, rid, menu.Id);

                menuDtoList.Add(menuDto);
            }

            return menuDtoList.OrderBy(x => x.DisplayOrder).ToList();
        }

        /// <summary>
        /// 递归获取该菜单所拥有的按钮
        /// </summary>
        /// <param name="malist">菜单按钮表</param>
        /// <param name="alist">按钮表</param>
        /// <param name="mid">菜单Id</param>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="rid">角色Id</param>
        /// <returns></returns>
        public static List<ActionDto> GetActionDtoList(List<MenuAction> malist, List<DFGK_WMS.Model.Models.Action> alist, long mid, List<RoleMenuAction> rmalist, long rid)
        {
            var actionDtoList = new List<ActionDto>();

            foreach (var menuAction in malist.Where(x => x.MenuId == mid))
            {
                var action = alist.FirstOrDefault(x => x.Id == menuAction.ActionId);

                if (action != null)
                {
                    actionDtoList.Add(new ActionDto
                    {
                        Id = action.Id,
                        ActionName = action.ActionName,
                        IsChecked = GetRoleActionDtoList(rmalist, rid, mid, action.Id)
                    });
                }
            }

            return actionDtoList;
        }

        /// <summary>
        /// 判断该角色是否拥有该菜单权限
        /// </summary>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="rid">角色Id</param>
        /// <param name="mid">菜单Id</param>
        /// <returns></returns>
        public static bool GetRoleMenuDtoList(List<RoleMenuAction> rmalist, long rid, long mid)
        {
            return rmalist.Any(x => x.RoleId == rid && x.MenuId == mid);
        }

        /// <summary>
        /// 判断该角色在该菜单中是否拥有按钮权限
        /// </summary>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="rid">角色Id</param>
        /// <param name="mid">菜单Id</param>
        /// <param name="aid">按钮Id</param>
        /// <returns></returns>
        public static bool GetRoleActionDtoList(List<RoleMenuAction> rmalist, long rid, long mid, long aid)
        {
            return rmalist.Any(x => x.RoleId == rid && x.MenuId == mid && x.ActionId == aid);
        }

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <param name="mname"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public List<MenuDto> GetMenuList(string mname, int status)
        {
            var mlist = _menuRepository.GetEntityAlls();
            if (!string.IsNullOrEmpty(mname))
            {
                mlist = mlist.Where(x => x.MenuName.Contains(mname));
            }
            if (status != 2)
            {
                mlist = mlist.Where(x => x.Status == status);
            }
            if (mlist.Any())
            {
                mlist = mlist.OrderBy(x => x.ParentId);
                var mmlist = mlist.FirstOrDefault();
                return GetMenuLists(mlist.ToList(), mmlist.ParentId.GetValueOrDefault());
            }
            var list = GetMenuLists(mlist.ToList(), 0);
            return list;
        }
        /// <summary>
        /// 递归显示菜单列表
        /// </summary>
        /// <param name="list"></param>
        /// <param name="pid"></param>
        /// <returns></returns>
        public static List<MenuDto> GetMenuLists(List<Menu> list, long pid)
        {
            try
            {
                return list.Where(x => x.ParentId == pid).Select(x => new MenuDto
                {
                    id = x.Id,
                    ParentId = x.ParentId,
                    MenuUrl = x.MenuUrl,
                    Meta = new MetaDto
                    {
                        MenuName = x.MenuName,
                        MenuIcon = x.MenuIcon,
                    },
                    Status = x.Status,
                    DisplayOrder = x.DisplayOrder,
                    children = GetMenuLists(list, x.Id)
                }).OrderBy(x => x.DisplayOrder).ToList();
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 分配权限
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool AddRoleMenuAction(CRoleMenuAction m)
        {         
            try
            {
                var rmalist = _roleMenuActionRepository.GetEntityWhereAll(x => x.RoleId == m.Rid);

                _unitOfWork.BeginTransaction();
                if (rmalist.Any())
                    _roleMenuActionRepository.DelEntityList(rmalist.ToList());
                foreach (var item in m.MidArr)
                {
                    var actionIds = item.Aids.Split(',').Select(aid => Convert.ToInt64(aid));

                    foreach (long actionId in actionIds)
                    {
                        var rma = new RoleMenuAction
                        {
                            Id= YitIdHelper.NextId(),
                            RoleId = m.Rid,
                            MenuId = item.Mid,
                            ActionId = actionId
                        };

                        _roleMenuActionRepository.AddEntity(rma);
                    }
                }
                if (_unitOfWork.SaveChangesEntity())
                {
                    _unitOfWork.CommitChanges();
                    return true;
                }
                _unitOfWork.RollbackChanges();
                return false;
            }
            catch (Exception)
            {
                _unitOfWork.RollbackChanges();
                throw;
            }
           
        }

        public bool AddMenuItem(Menu m)
        {
            _menuRepository.AddEntity(m);
            return _unitOfWork.SaveChangesEntity();
        }

        public Menu? GetMenuItem(long id)
        {
            return _menuRepository.QueryEntityById(id);
        }

        public bool UpdMenuItem(Menu m)
        {
            _menuRepository.UpdEntity(m);
            return _unitOfWork.SaveChangesEntity();
        }
    }
}
